home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / HTMLParser.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-13  |  9.4 KB  |  333 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. import markupbase
  5. import re
  6. interesting_normal = re.compile('[&<]')
  7. interesting_cdata = re.compile('<(/|\\Z)')
  8. incomplete = re.compile('&[a-zA-Z#]')
  9. entityref = re.compile('&([a-zA-Z][-.a-zA-Z0-9]*)[^a-zA-Z0-9]')
  10. charref = re.compile('&#(?:[0-9]+|[xX][0-9a-fA-F]+)[^0-9a-fA-F]')
  11. starttagopen = re.compile('<[a-zA-Z]')
  12. piclose = re.compile('>')
  13. commentclose = re.compile('--\\s*>')
  14. tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
  15. attrfind = re.compile('\\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\\s*=\\s*(\\\'[^\\\']*\\\'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$\\(\\)_#=~@]*))?')
  16. locatestarttagend = re.compile('\n  <[a-zA-Z][-.a-zA-Z0-9:_]*          # tag name\n  (?:\\s+                             # whitespace before attribute name\n    (?:[a-zA-Z_][-.:a-zA-Z0-9_]*     # attribute name\n      (?:\\s*=\\s*                     # value indicator\n        (?:\'[^\']*\'                   # LITA-enclosed value\n          |\\"[^\\"]*\\"                # LIT-enclosed value\n          |[^\'\\">\\s]+                # bare value\n         )\n       )?\n     )\n   )*\n  \\s*                                # trailing whitespace\n', re.VERBOSE)
  17. endendtag = re.compile('>')
  18. endtagfind = re.compile('</\\s*([a-zA-Z][-.a-zA-Z0-9:_]*)\\s*>')
  19.  
  20. class HTMLParseError(Exception):
  21.     
  22.     def __init__(self, msg, position = (None, None)):
  23.         self.msg = msg
  24.         self.lineno = position[0]
  25.         self.offset = position[1]
  26.  
  27.     
  28.     def __str__(self):
  29.         result = self.msg
  30.         if self.lineno is not None:
  31.             result = result + ', at line %d' % self.lineno
  32.         
  33.         if self.offset is not None:
  34.             result = result + ', column %d' % (self.offset + 1)
  35.         
  36.         return result
  37.  
  38.  
  39.  
  40. class HTMLParser(markupbase.ParserBase):
  41.     CDATA_CONTENT_ELEMENTS = ('script', 'style')
  42.     
  43.     def __init__(self):
  44.         self.reset()
  45.  
  46.     
  47.     def reset(self):
  48.         self.rawdata = ''
  49.         self.lasttag = '???'
  50.         self.interesting = interesting_normal
  51.         markupbase.ParserBase.reset(self)
  52.  
  53.     
  54.     def feed(self, data):
  55.         self.rawdata = self.rawdata + data
  56.         self.goahead(0)
  57.  
  58.     
  59.     def close(self):
  60.         self.goahead(1)
  61.  
  62.     
  63.     def error(self, message):
  64.         raise HTMLParseError(message, self.getpos())
  65.  
  66.     __starttag_text = None
  67.     
  68.     def get_starttag_text(self):
  69.         return self._HTMLParser__starttag_text
  70.  
  71.     
  72.     def set_cdata_mode(self):
  73.         self.interesting = interesting_cdata
  74.  
  75.     
  76.     def clear_cdata_mode(self):
  77.         self.interesting = interesting_normal
  78.  
  79.     
  80.     def goahead(self, end):
  81.         rawdata = self.rawdata
  82.         i = 0
  83.         n = len(rawdata)
  84.         while i < n:
  85.             match = self.interesting.search(rawdata, i)
  86.             if match:
  87.                 j = match.start()
  88.             else:
  89.                 j = n
  90.             if i < j:
  91.                 self.handle_data(rawdata[i:j])
  92.             
  93.             i = self.updatepos(i, j)
  94.             if i == n:
  95.                 break
  96.             
  97.             startswith = rawdata.startswith
  98.             if startswith('<', i):
  99.                 if starttagopen.match(rawdata, i):
  100.                     k = self.parse_starttag(i)
  101.                 elif startswith('</', i):
  102.                     k = self.parse_endtag(i)
  103.                 elif startswith('<!--', i):
  104.                     k = self.parse_comment(i)
  105.                 elif startswith('<?', i):
  106.                     k = self.parse_pi(i)
  107.                 elif startswith('<!', i):
  108.                     k = self.parse_declaration(i)
  109.                 elif i + 1 < n:
  110.                     self.handle_data('<')
  111.                     k = i + 1
  112.                 else:
  113.                     break
  114.                 if k < 0:
  115.                     if end:
  116.                         self.error('EOF in middle of construct')
  117.                     
  118.                     break
  119.                 
  120.                 i = self.updatepos(i, k)
  121.                 continue
  122.             if startswith('&#', i):
  123.                 match = charref.match(rawdata, i)
  124.                 if match:
  125.                     name = match.group()[2:-1]
  126.                     self.handle_charref(name)
  127.                     k = match.end()
  128.                     if not startswith(';', k - 1):
  129.                         k = k - 1
  130.                     
  131.                     i = self.updatepos(i, k)
  132.                     continue
  133.                 else:
  134.                     break
  135.             match
  136.             if startswith('&', i):
  137.                 match = entityref.match(rawdata, i)
  138.                 if match:
  139.                     name = match.group(1)
  140.                     self.handle_entityref(name)
  141.                     k = match.end()
  142.                     if not startswith(';', k - 1):
  143.                         k = k - 1
  144.                     
  145.                     i = self.updatepos(i, k)
  146.                     continue
  147.                 
  148.                 match = incomplete.match(rawdata, i)
  149.                 if match:
  150.                     if end and match.group() == rawdata[i:]:
  151.                         self.error('EOF in middle of entity or char ref')
  152.                     
  153.                     break
  154.                 elif i + 1 < n:
  155.                     self.handle_data('&')
  156.                     i = self.updatepos(i, i + 1)
  157.                 else:
  158.                     break
  159.             match
  160.         if end and i < n:
  161.             self.handle_data(rawdata[i:n])
  162.             i = self.updatepos(i, n)
  163.         
  164.         self.rawdata = rawdata[i:]
  165.  
  166.     
  167.     def parse_pi(self, i):
  168.         rawdata = self.rawdata
  169.         match = piclose.search(rawdata, i + 2)
  170.         if not match:
  171.             return -1
  172.         
  173.         j = match.start()
  174.         self.handle_pi(rawdata[i + 2:j])
  175.         j = match.end()
  176.         return j
  177.  
  178.     
  179.     def parse_starttag(self, i):
  180.         self._HTMLParser__starttag_text = None
  181.         endpos = self.check_for_whole_start_tag(i)
  182.         if endpos < 0:
  183.             return endpos
  184.         
  185.         rawdata = self.rawdata
  186.         self._HTMLParser__starttag_text = rawdata[i:endpos]
  187.         attrs = []
  188.         match = tagfind.match(rawdata, i + 1)
  189.         k = match.end()
  190.         self.lasttag = tag = rawdata[i + 1:k].lower()
  191.         while k < endpos:
  192.             m = attrfind.match(rawdata, k)
  193.             if not m:
  194.                 break
  195.             
  196.             (attrname, rest, attrvalue) = m.group(1, 2, 3)
  197.             if not rest:
  198.                 attrvalue = None
  199.             elif "'" == "'":
  200.                 pass
  201.             elif not "'" == attrvalue[-1:]:
  202.                 if '"' == '"':
  203.                     pass
  204.                 elif '"' == attrvalue[-1:]:
  205.                     attrvalue = attrvalue[1:-1]
  206.                     attrvalue = self.unescape(attrvalue)
  207.                 
  208.             attrs.append((attrname.lower(), attrvalue))
  209.             k = m.end()
  210.             continue
  211.             attrvalue[:1]
  212.         end = rawdata[k:endpos].strip()
  213.         if end not in ('>', '/>'):
  214.             (lineno, offset) = self.getpos()
  215.             if '\n' in self._HTMLParser__starttag_text:
  216.                 lineno = lineno + self._HTMLParser__starttag_text.count('\n')
  217.                 offset = len(self._HTMLParser__starttag_text) - self._HTMLParser__starttag_text.rfind('\n')
  218.             else:
  219.                 offset = offset + len(self._HTMLParser__starttag_text)
  220.             self.error('junk characters in start tag: %r' % (rawdata[k:endpos][:20],))
  221.         
  222.         if end.endswith('/>'):
  223.             self.handle_startendtag(tag, attrs)
  224.         else:
  225.             self.handle_starttag(tag, attrs)
  226.             if tag in self.CDATA_CONTENT_ELEMENTS:
  227.                 self.set_cdata_mode()
  228.             
  229.         return endpos
  230.  
  231.     
  232.     def check_for_whole_start_tag(self, i):
  233.         rawdata = self.rawdata
  234.         m = locatestarttagend.match(rawdata, i)
  235.         if m:
  236.             j = m.end()
  237.             next = rawdata[j:j + 1]
  238.             if next == '>':
  239.                 return j + 1
  240.             
  241.             if next == '/':
  242.                 if rawdata.startswith('/>', j):
  243.                     return j + 2
  244.                 
  245.                 if rawdata.startswith('/', j):
  246.                     return -1
  247.                 
  248.                 self.updatepos(i, j + 1)
  249.                 self.error('malformed empty start tag')
  250.             
  251.             if next == '':
  252.                 return -1
  253.             
  254.             if next in 'abcdefghijklmnopqrstuvwxyz=/ABCDEFGHIJKLMNOPQRSTUVWXYZ':
  255.                 return -1
  256.             
  257.             self.updatepos(i, j)
  258.             self.error('malformed start tag')
  259.         
  260.         raise AssertionError('we should not get here!')
  261.  
  262.     
  263.     def parse_endtag(self, i):
  264.         rawdata = self.rawdata
  265.         match = endendtag.search(rawdata, i + 1)
  266.         if not match:
  267.             return -1
  268.         
  269.         j = match.end()
  270.         match = endtagfind.match(rawdata, i)
  271.         if not match:
  272.             self.error('bad end tag: %r' % (rawdata[i:j],))
  273.         
  274.         tag = match.group(1)
  275.         self.handle_endtag(tag.lower())
  276.         self.clear_cdata_mode()
  277.         return j
  278.  
  279.     
  280.     def handle_startendtag(self, tag, attrs):
  281.         self.handle_starttag(tag, attrs)
  282.         self.handle_endtag(tag)
  283.  
  284.     
  285.     def handle_starttag(self, tag, attrs):
  286.         pass
  287.  
  288.     
  289.     def handle_endtag(self, tag):
  290.         pass
  291.  
  292.     
  293.     def handle_charref(self, name):
  294.         pass
  295.  
  296.     
  297.     def handle_entityref(self, name):
  298.         pass
  299.  
  300.     
  301.     def handle_data(self, data):
  302.         pass
  303.  
  304.     
  305.     def handle_comment(self, data):
  306.         pass
  307.  
  308.     
  309.     def handle_decl(self, decl):
  310.         pass
  311.  
  312.     
  313.     def handle_pi(self, data):
  314.         pass
  315.  
  316.     
  317.     def unknown_decl(self, data):
  318.         self.error('unknown declaration: %r' % (data,))
  319.  
  320.     
  321.     def unescape(self, s):
  322.         if '&' not in s:
  323.             return s
  324.         
  325.         s = s.replace('<', '<')
  326.         s = s.replace('>', '>')
  327.         s = s.replace(''', "'")
  328.         s = s.replace('"', '"')
  329.         s = s.replace('&', '&')
  330.         return s
  331.  
  332.  
  333.